package cn.com.cjwsjy.monitor.platform.earlywarn.service.impl;

import cn.com.cjwsjy.monitor.platform.earlywarn.dao.*;
import cn.com.cjwsjy.monitor.platform.earlywarn.entity.EarlyWarningManagementEntity;
import cn.com.cjwsjy.monitor.platform.earlywarn.entity.EarlyWarningPlanEntity;
import cn.com.cjwsjy.monitor.platform.earlywarn.entity.engineers.EngineeringsEntity;
import cn.com.cjwsjy.monitor.platform.earlywarn.entity.engineers.PositionsEntity;
import cn.com.cjwsjy.monitor.platform.earlywarn.requestVO.EarlyWarningPlanQuery;
import cn.com.cjwsjy.monitor.platform.earlywarn.responseVO.EarlyWarningPlanVO;
import cn.com.cjwsjy.monitor.platform.earlywarn.service.EarlyWarningPlanService;
import cn.com.cjwsjy.monitor.platform.earlywarn.utils.IdWorker;
import cn.com.cjwsjy.monitor.platform.earlywarn.utils.R;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class EarlyWarningPlanServiceImpl implements EarlyWarningPlanService {
    @Autowired
    private EngineeringsDao engineeringsDao;

    @Autowired
    private PositionsDao positionsDao;

    @Autowired
    private EarlyWarningManagementDao earlyWarningManagementDao;

    @Autowired
    private EarlyWarningPlanDao earlyWarningPlanDao;

    @Autowired
    private WarningMessageDao warningMessageDao;

    @Autowired
    private Environment env;

    /**
     * 获取所有工程部位，从其他微服务复制过来的代码
     * 合并到原系统后，通过openfeign直接调用 dataEarlywarnFeignService.getAllPositions();
     *
     * @return
     */
    @Override
    public R getAllPositions() {
        List<PositionsEntity> list = new ArrayList<>();
        //获取所有工程对象通过工程对象获取工程部位
        List<EngineeringsEntity> entities = engineeringsDao.selectList(null);
        for (EngineeringsEntity entity : entities) {
            PositionsEntity positionsEntity = new PositionsEntity();
            positionsEntity.setName(entity.getEngineering());
            positionsEntity.setId(entity.getId());
            List<PositionsEntity> positionsEntityList = positionsDao.selectList(new QueryWrapper<PositionsEntity>().eq("eng_id", entity.getId()));
            //找到所有一级分类（在本系统下可以说是二级）
            List<PositionsEntity> level1Menus = positionsEntityList.stream().filter(item ->
                    item.getFatherId() == null
            ).map(item -> {
                //递归获取子菜单
                item.setChildren(getChildren(item, positionsEntityList));
                return item;
            }).collect(Collectors.toList());
            //将结果集添加到list集合里面
            positionsEntity.setChildren(level1Menus);
            list.add(positionsEntity);
        }
        return R.ok().put("data", list);
    }

    /**
     * 递归获取所有子菜单
     *
     * @param root 当前菜单
     * @param all  所有菜单
     * @return
     */
    public List<PositionsEntity> getChildren(PositionsEntity root, List<PositionsEntity> all) {
        List<PositionsEntity> children = all.stream()
                .filter(item -> (item.getFatherId() == null ? 0 : item.getFatherId()) == (root.getId() == null ? 0 : root.getId()))
                .map(item -> {
                    item.setChildren(getChildren(item, all));
                    return item;
                }).collect(Collectors.toList());
        return children;
    }

    /**
     * 获取所有预警等级
     *
     * @return
     */
    @Override
    public R getAllLevels() {
        List<EarlyWarningManagementEntity> earlyWarningLevels = earlyWarningManagementDao.selectList(null);
        return R.ok().put("data", earlyWarningLevels);
    }

    /**
     * 添加应急预案
     *
     * @param docName          文件名
     * @param warningLevel     预警等级
     * @param applicablePeriod 适用日期
     * @param positionName     工程部位
     * @param file             上传文件
     * @param uploadPerson     上传人
     * @return
     */
    @Override
    public R addPlan(String docName, String warningLevel, String applicablePeriod, String positionName, MultipartFile file, String uploadPerson) throws Exception {
        IdWorker idWorker = new IdWorker();
        Long id = idWorker.nextId();
        EarlyWarningPlanEntity earlyWarningPlanEntity = new EarlyWarningPlanEntity();
        earlyWarningPlanEntity.setId(id);
        earlyWarningPlanEntity.setDocName(docName);
        earlyWarningPlanEntity.setWarningLevel(warningLevel);
        earlyWarningPlanEntity.setApplicablePeriod(applicablePeriod);
        earlyWarningPlanEntity.setPositionName(positionName);
        earlyWarningPlanEntity.setUploadPerson(uploadPerson);
        if (file.isEmpty()) {
            return R.error("上传文件为空，请重试！");
        }
        //获取原始文件名
        String realFileName = file.getOriginalFilename();
        assert realFileName != null;
        earlyWarningPlanEntity.setOriginalFileName(realFileName);
        //获取文件后缀名
        String suffix = realFileName.substring(realFileName.lastIndexOf("."));
        earlyWarningPlanEntity.setDocType(suffix);
        //设置新的唯一的文件名，避免上传的文件名重复
        String newFileName = id + suffix;
        //设置存放文件的磁盘路径
        String filePath = env.getProperty("early-warning-plan.file-storage-path");
        if (filePath == null || filePath.trim().isEmpty()) {
            filePath = "D:/应急预案";
        }

        File uploadFile = new File(filePath, newFileName);
        String fileStorePath = uploadFile.getAbsolutePath();
        //获取文件大小并转换为kb单位
        BigDecimal b = BigDecimal.valueOf(Float.parseFloat(String.valueOf(file.getSize())) / 1024);
        float size = b.setScale(2, RoundingMode.HALF_UP).floatValue();
        String fileSize = size + "kb";
        earlyWarningPlanEntity.setDocSize(fileSize);
        Date date = new Date();
        earlyWarningPlanEntity.setUploadTime(date);
        earlyWarningPlanEntity.setFilePath(fileStorePath);
        earlyWarningPlanDao.insert(earlyWarningPlanEntity);
        //存放文件到指定路径
        FileUtils.writeByteArrayToFile(uploadFile, file.getBytes());
        return R.ok("上传成功");
    }

    /**
     * 获取所有已添加过的适用时期
     *
     * @return
     */
    @Override
    public R getAllPeriods() {
        QueryWrapper<EarlyWarningPlanEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.select();
        //获取数据表中所有数据
        List<EarlyWarningPlanEntity> earlyWarningPlanEntityList = earlyWarningPlanDao.selectList(queryWrapper);
        //applicationPeriodList列表存放所有的适用时期
        List<String> applicationPeriodList = new ArrayList<>();
        for (EarlyWarningPlanEntity earlyWarningPlanEntity : earlyWarningPlanEntityList) {
            String applicationPeriod = earlyWarningPlanEntity.getApplicablePeriod();
            applicationPeriodList.add(applicationPeriod);
        }
        return R.ok().put("applicationPeriod", applicationPeriodList);
    }

    /**
     * 修改应急预案
     *
     * @param id               应急预案id
     * @param docName          文件名
     * @param warningLevel     预警等级
     * @param applicablePeriod 适用日期
     * @param positionName     工程部位
     * @param file             上传文件
     * @param uploadPerson     上传人
     * @return
     */
    @Override
    public R updatePlan(Long id, String docName, String warningLevel, String applicablePeriod, String positionName, MultipartFile file, String uploadPerson) throws Exception {
        EarlyWarningPlanEntity earlyWarningPlanEntity = new EarlyWarningPlanEntity();
        earlyWarningPlanEntity.setId(id);
        earlyWarningPlanEntity.setDocName(docName);
        earlyWarningPlanEntity.setWarningLevel(warningLevel);
        earlyWarningPlanEntity.setApplicablePeriod(applicablePeriod);
        earlyWarningPlanEntity.setPositionName(positionName);
        earlyWarningPlanEntity.setUploadPerson(uploadPerson);

        if (file != null && !file.isEmpty()) {
            //先删除之前存在磁盘的文件
            EarlyWarningPlanEntity oldEarlyWarningPlanEntity = earlyWarningPlanDao.selectById(id);
            String oldFilePath = oldEarlyWarningPlanEntity.getFilePath();
            File fileDelete = new File(oldFilePath);
            if (fileDelete.exists()) {
                if (!fileDelete.delete()) {
                    return R.error("旧文件删除失败，请联系管理员！");
                }
            }

            //获取原始文件名
            String realFileName = file.getOriginalFilename();
            assert realFileName != null;
            earlyWarningPlanEntity.setOriginalFileName(realFileName);
            //获取文件后缀名
            String suffix = realFileName.substring(realFileName.lastIndexOf("."));
            earlyWarningPlanEntity.setDocType(suffix);
            //设置存放文件的磁盘路径
            String filePath = oldFilePath.substring(0, oldFilePath.indexOf('.')) + suffix;
            File uploadFile = new File(filePath);
            //获取文件大小并转换为kb单位
            BigDecimal b = BigDecimal.valueOf(Float.parseFloat(String.valueOf(file.getSize())) / 1024);
            float size = b.setScale(2, RoundingMode.HALF_UP).floatValue();
            String fileSize = size + "kb";
            earlyWarningPlanEntity.setDocSize(fileSize);
            Date date = new Date();
            earlyWarningPlanEntity.setUploadTime(date);
            earlyWarningPlanEntity.setFilePath(filePath);
            earlyWarningPlanDao.updateById(earlyWarningPlanEntity);
            //存放文件到指定路径
            FileUtils.writeByteArrayToFile(uploadFile, file.getBytes());
            return R.ok("更新成功");
        }

        earlyWarningPlanDao.updateById(earlyWarningPlanEntity);
        return R.ok("更新成功");
    }

    /**
     * 删除应急预案
     *
     * @param id 应急预案id
     * @return
     */
    @Override
    public R deletePlan(Long id) {
        EarlyWarningPlanEntity earlyWarningPlanEntity = earlyWarningPlanDao.selectById(id);
        if (null == earlyWarningPlanEntity) {
            return R.error("id不存在！");
        }
        String filePath = earlyWarningPlanEntity.getFilePath();
        //删除预案中存放在磁盘的文件
        File fileDelete = new File(filePath);
        if (fileDelete.exists()) {
            if (!fileDelete.delete()) {
                return R.error("旧文件删除失败，请联系管理员！");
            }
        }
        earlyWarningPlanDao.deleteById(id);
        return R.ok("删除成功");
    }

    /**
     * 条件查询应急预案
     *
     * @param earlyWarningPlanQuery 查询条件
     * @return
     */
    @Override
    public R queryPlan(EarlyWarningPlanQuery earlyWarningPlanQuery) {
        String positionName = earlyWarningPlanQuery.getPositionName();
        String applicablePeriod = earlyWarningPlanQuery.getApplicablePeriod();
        String keyword = earlyWarningPlanQuery.getKeyword();
        String planIds = earlyWarningPlanQuery.getPlanIds();
        // planIds存在时，忽略其他参数，直接用planIds查询
        if(planIds != null && !planIds.isEmpty()){
            List<EarlyWarningPlanVO> earlyWarningPlanVO = getPlansByIds(planIds);
            return R.ok().put("data", earlyWarningPlanVO);
        }
        QueryWrapper<EarlyWarningPlanEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(positionName != null && !positionName.isEmpty(), "position_name", positionName)
                .eq(applicablePeriod != null && !applicablePeriod.isEmpty(), "applicable_period", applicablePeriod)
                .like(keyword != null && !keyword.trim().isEmpty(), "doc_name", keyword);
        List<EarlyWarningPlanEntity> earlyWarningPlans = earlyWarningPlanDao.selectList(queryWrapper);
        List<EarlyWarningPlanVO> earlyWarningPlanVO = new ArrayList<>();
        for (EarlyWarningPlanEntity earlyWarningPlan : earlyWarningPlans) {
            EarlyWarningPlanVO planVO = new EarlyWarningPlanVO();
            planVO.setId(earlyWarningPlan.getId());
            planVO.setDocName(earlyWarningPlan.getDocName());
            planVO.setApplicablePeriod(earlyWarningPlan.getApplicablePeriod());
            planVO.setDocSize(earlyWarningPlan.getDocSize());
            planVO.setWarningLevel(earlyWarningPlan.getWarningLevel());
            planVO.setDocType(earlyWarningPlan.getDocType());
            planVO.setPositionName(earlyWarningPlan.getPositionName());
            planVO.setUploadPerson(earlyWarningPlan.getUploadPerson());
            planVO.setUploadTime(earlyWarningPlan.getUploadTime());
            planVO.setOriginalFileName(earlyWarningPlan.getOriginalFileName());
            earlyWarningPlanVO.add(planVO);
        }
        return R.ok().put("data", earlyWarningPlanVO);
    }

    /**
     * 通过预警消息设置表id查询应急预案信息
     * @param id 预警消息设置表id
     * @return
     */
    @Override
    public R getPlanInfoByWarningMessageId(int id) {
        WarningMessageEntity warningMessage = warningMessageDao.selectById(id);
        if(null == warningMessage){
            return R.error("不存在该id，请检查id是否正确！");
        }
        String planIds = warningMessage.getPlanIds();
        if(null == planIds || planIds.trim().isEmpty()){
            return R.ok().put("data","");
        }
        List<EarlyWarningPlanVO> earlyWarningPlanVO = getPlansByIds(planIds);
        return R.ok().put("data", earlyWarningPlanVO);
    }

    /**
     * 下载应急预案
     *
     * @param id       应急预案对应的id
     * @param response 响应体
     * @return
     */
    @Override
    public R downloadPlan(Long id, HttpServletResponse response) {
        EarlyWarningPlanEntity earlyWarningPlan = earlyWarningPlanDao.selectById(id);
        if (null == earlyWarningPlan) {
            return R.error("不存在对应id的应急预案文件！");
        }
        String path = earlyWarningPlan.getFilePath();
        String docName = earlyWarningPlan.getDocName();
        String docType = earlyWarningPlan.getDocType();
        String fileName = docName + docType;
        File file = new File(path);
        try {
            FileInputStream fileInputStream = new FileInputStream(file);
            ServletOutputStream outputStream = response.getOutputStream();
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            // copy方法内部关闭了 fileInputStream 和 outputStream
            FileCopyUtils.copy(fileInputStream, outputStream);
        } catch (FileNotFoundException e) {
            return R.error("请求的文件已被删除！");
        } catch (IOException e1) {
            e1.printStackTrace();
            return R.error("下载出错，请重试！");
        }
        return R.ok("下载成功！");
    }

    public List<EarlyWarningPlanVO> getPlansByIds(String planIds){
        String[] ids = planIds.split(",");
        List<EarlyWarningPlanVO> earlyWarningPlanVO = new ArrayList<>();
        for(String planId : ids){
            EarlyWarningPlanEntity earlyWarningPlan = earlyWarningPlanDao.selectById(planId);
            if(null == earlyWarningPlan){
                continue;
            }
            EarlyWarningPlanVO planVO = new EarlyWarningPlanVO();
            planVO.setId(earlyWarningPlan.getId());
            planVO.setDocName(earlyWarningPlan.getDocName());
            planVO.setApplicablePeriod(earlyWarningPlan.getApplicablePeriod());
            planVO.setDocSize(earlyWarningPlan.getDocSize());
            planVO.setWarningLevel(earlyWarningPlan.getWarningLevel());
            planVO.setDocType(earlyWarningPlan.getDocType());
            planVO.setPositionName(earlyWarningPlan.getPositionName());
            planVO.setUploadPerson(earlyWarningPlan.getUploadPerson());
            planVO.setUploadTime(earlyWarningPlan.getUploadTime());
            planVO.setOriginalFileName(earlyWarningPlan.getOriginalFileName());
            earlyWarningPlanVO.add(planVO);
        }
        return earlyWarningPlanVO;
    }
}
